package com.zclcs.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zclcs.mapper.RoleUserMapper;
import com.zclcs.mapper.UserMapper;
import com.zclcs.model.CurrentUser;
import com.zclcs.model.DataRet;
import com.zclcs.model.Menu;
import com.zclcs.model.RoleUser;
import com.zclcs.model.User;
import com.zclcs.service.UserService;
import com.zclcs.utils.ServletContextUtil;

/**
 * service实现层
 * 
 * @author 周成龙
 *
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {

	@Autowired
	private UserMapper userMapper;

	@Autowired
	private RoleUserMapper roleUserMapper;

	@Override
	public User findByUsername(String username) {
		return userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
	}

	@Override
	public DataRet<Object> changePassword(String newPassword, String oldPassword) {
		DataRet<Object> dataRet = new DataRet<Object>();
		String oldPs = new SimpleHash("MD5", oldPassword, ByteSource.Util.bytes(ServletContextUtil.getUsername()), 1024)
				.toHex();
		User userApp = new User();
		userApp.setUsername(ServletContextUtil.getUsername());
		userApp.setPassword(oldPs);
		User selectOne = userMapper.selectOne(new QueryWrapper<User>(userApp));
		if (selectOne != null) {
			String newPs = new SimpleHash("MD5", newPassword, ByteSource.Util.bytes(ServletContextUtil.getUsername()),
					1024).toHex();
			selectOne.setPassword(newPs);
			userMapper.updateById(selectOne);
			dataRet.setCode(0000000);
			dataRet.setMessage("修改成功");
			Subject subject = SecurityUtils.getSubject();
			subject.logout();
		} else {
			dataRet.setCode(9999999);
			dataRet.setMessage("修改失败，请检查您的原密码是否正确");
		}
		return dataRet;
	}

	@Override
	public Integer checkUsername(User user) {
		return userMapper.selectCount(new QueryWrapper<User>(user));
	}

	@Override
	public CurrentUser getCurrentUser(User user) {
		CurrentUser currentUser = new CurrentUser();
		User user2 = findByUsername(user.getUsername());
		currentUser.setName(user2.getName());
		String[] roles = null;
		if (userMapper.selectIsAdmin(new QueryWrapper<User>().eq("username", user2.getUsername())) > 0) {
			roles = userMapper.selectAdminRoles();
		} else {
			roles = userMapper.selectUserRoles(user2);
		}
		currentUser.setRoles(roles);
		currentUser.setAvatar("");
		currentUser.setIntroduction("");
		return currentUser;
	}

	@Override
	public List<Menu> selectAccessMenus(User user) {
		List<Menu> topMenus = null;
		if (userMapper.selectIsAdmin(new QueryWrapper<User>().eq("username", user.getUsername())) > 0) {
			topMenus = userMapper.selectAdminMenus();
		} else {
			topMenus = userMapper.selectAdminMenus();
		}
		for (Menu menu : topMenus) {
			List<Menu> childrenMenus = new ArrayList<Menu>();
			if (userMapper.selectIsAdmin(new QueryWrapper<User>().eq("username", user.getUsername())) > 0) {
				selectAdminChildrenMenus(menu, user, childrenMenus);
			} else {
				selectChildrenMenus(menu, user, childrenMenus);
			}
			menu.setChildren(childrenMenus);
		}
		List<Menu> reMenus = new ArrayList<Menu>();
		for (Menu menu : topMenus) {
			Menu menu2 = new Menu();
			menu2.setTitle(menu.getMenuName());
			menu2.setName(menu.getName());
			List<String> roles = new ArrayList<String>();
			if (menu.getPermission() != null && !"".equals(menu.getPermission())) {
				roles.add(menu.getPermission());
			}
			for (Menu menu3 : menu.getChildren()) {
				roles.add(menu3.getPermission());
			}
			menu2.setRoles(roles);
			reMenus.add(menu2);
		}
		return reMenus;
	}

	/**
	 * 递归算法取出所有菜单子级
	 * 
	 * @param menu          菜单对象
	 * @param user          用户对象
	 * @param childrenMenus 子菜单集合
	 * @return 该菜单对象的所有菜单子级
	 */
	private void selectChildrenMenus(Menu menu, User user, List<Menu> childrenMenus) {
		user.setParentId(menu.getId());
		List<Menu> selectChildrenMenus = userMapper.selectChildrenMenus(user);
		childrenMenus.addAll(selectChildrenMenus);
		for (Menu menu2 : selectChildrenMenus) {
			selectChildrenMenus(menu2, user, childrenMenus);
		}
	}

	/**
	 * 递归算法取出所有菜单子级
	 * 
	 * @param menu          菜单对象
	 * @param user          用户对象
	 * @param childrenMenus 子菜单集合
	 * @return 该菜单对象的所有菜单子级
	 */
	private void selectAdminChildrenMenus(Menu menu, User user, List<Menu> childrenMenus) {
		user.setParentId(menu.getId());
		List<Menu> selectChildrenMenus = userMapper.selectAdminChildrenMenus(user);
		childrenMenus.addAll(selectChildrenMenus);
		for (Menu menu2 : selectChildrenMenus) {
			selectChildrenMenus(menu2, user, childrenMenus);
		}
	}

	@Override
	public String[] selectUserPermissions(User user) {
		return userMapper.selectUserRoles(user);
	}

	@Override
	public IPage<User> selectUserPage(User user) {
		Page<User> page = new Page<User>(user.getPage(), user.getLimit());
		return userMapper.selectPage(page,
				new QueryWrapper<User>()
						.like(user.getName() != null && !user.getName().equals(""), "name", user.getName())
						.like(user.getUsername() != null && !user.getName().equals(""), "username", user.getUsername())
						.orderBy(user.getSort() != null, user.getSort().equals("asc"), "name"));
	}

	@Override
	public void insertUser(User user) {
		/*
		 * MD5加密： 使用SimpleHash类对原始密码进行加密。 第一个参数代表使用MD5方式加密 第二个参数为原始密码 第三个参数为盐值，即用户名
		 * 第四个参数为加密次数 最后用toHex()方法将加密后的密码转成String
		 */
		String newPs = new SimpleHash("MD5", "123456", ByteSource.Util.bytes(user.getUsername()), 1024).toHex();
		user.setPassword(newPs); // 密码
		userMapper.insert(user);
	}

	@Override
	public DataRet<Object> deleteUser(List<String> ids) {
		if (userMapper.selectIsAdmin(new QueryWrapper<User>().in("u.uuid", ids)) > 0) {
			String[] adminUser = userMapper.selectAdminUser(new QueryWrapper<User>().in("u.uuid", ids));
			String jsonString = JSON.toJSONString(adminUser);
			return new DataRet<>(999, "请勿删除以下用户：" + jsonString);
		}
		int deleteBatchIds = userMapper.deleteBatchIds(ids);
		roleUserMapper.delete(new QueryWrapper<RoleUser>().in("user_id", ids));
		return new DataRet<>("删除成功，删除的记录数：" + deleteBatchIds);
	}

	@Override
	public void updateUser(User user) {
		userMapper.update(user, new QueryWrapper<User>().eq("uuid", user.getUuid()));
	}

	@Override
	public Boolean validUsername(User user) {
		Integer selectCount = userMapper.selectCount(new QueryWrapper<User>().eq("username", user.getUsername()));
		if (null != user.getUuid() && !"".equals(user.getUuid())) {
			User user2 = userMapper.selectOne(new QueryWrapper<User>().eq("uuid", user.getUuid()));
			return (user.getUsername().equals(user2.getUsername())) ? true : (selectCount == 1) ? false : true;
		} else {
			return (selectCount == 1) ? false : true;
		}
	}

	@Override
	public void resetPassword() {
		String username = ServletContextUtil.getUsername();
		String password = new SimpleHash("MD5", "123456", ByteSource.Util.bytes(username), 1024).toHex();
		User user = new User();
		user.setPassword(password);
		userMapper.update(user, new QueryWrapper<User>().eq("username", username));
	}
}
